from typing import Dict, Optional, Callable
from datetime import datetime
import attr
import pandas as pd

from . import base
from . constants import *


class DataSet:
    def get_data(self, freq: str, count: int, fields: str) -> pd.DataFrame:
        ...


@attr.s(slots=True)
class SimpleSubParams:
    symbols: str = attr.ib('')
    frequency: str = attr.ib('')
    count: int = attr.ib(0)
    wait_group: bool = attr.ib(False)
    wait_group_timeout: str = attr.ib('10s')
    unsubscribe_previous: bool = attr.ib(False)


@attr.s(slots=True)
class SimpleContext(base.Context):
    mode: int = attr.ib()
    datasets: Dict[str, DataSet] = attr.ib()

    subscribe_params: SimpleSubParams = attr.ib(factory=SimpleSubParams, init=False)

    def subscribe(self,
                  symbols: str,
                  frequency='1d',
                  count: int = 1,
                  wait_group: bool = False,
                  wait_group_timeout: str = '10s',
                  unsubscribe_previous: bool = False):
        self.subscribe_params = SimpleSubParams(
            symbols=symbols,
            frequency=frequency,
            count=count,
            wait_group=wait_group,
            wait_group_timeout=wait_group_timeout,
            unsubscribe_previous=unsubscribe_previous,
        )

    def get_data(self, symbol: str, freq: str, count: int, fields: str) -> pd.DataFrame:
        """获取订阅的bar或tick滑窗，数据为包含当前时刻推送bar或tick的前count条bar或者tick数据"""
        return self.datasets[symbol].get_data(freq=freq, count=count, fields=fields)

    def get_account(self, account_id: Optional[str] = None) -> Account:
        """账户信息，默认返回默认账户, 如多个账户需指定account_id"""
        ...

    def order_volume(self,
                     symbol: str,
                     volume: int,
                     side: int,
                     position_effect: int,
                     order_type: int):
        ...

    def schedule(self, schedule_func: Callable[['Context'], ...], date_rule: str, time_rule: str):
        ...

    def history_n(self,
                  symbol: str,
                  frequency: str,
                  end_time: datetime,
                  fields: str,
                  count: int) -> pd.DataFrame:
        ...

    def current(self, symbol: str) -> pd.DataFrame:
        ...


@attr.s(slots=True)
class SimpleBackend:
    strategy: base.Strategy = attr.ib()

    def run(self,
            mode: int,
            backtest_start_time: str,
            backtest_end_time: str,
            backtest_initial_cash: float,
            backtest_commission_ratio: float,
            backtest_slippage: float):
        # 初始化context
        context = SimpleContext(mode=mode)
        # 初始化策略
        self.strategy.on_init(context)
